package services

import (
	"gitee.com/igolang/imoney/internal/app/system/entities"
	"gitee.com/igolang/imoney/internal/app/system/entities/constants"
	"gitee.com/igolang/imoney/internal/app/system/tools"
	"gitee.com/igolang/imoney/internal/common/httpResp"
	"gitee.com/igolang/imoney/internal/common/tools/storage"
	"gitee.com/igolang/imoney/internal/models/dao"
	"gitee.com/igolang/imoney/internal/models/model"
	"gitee.com/igolang/pkg/xgorm"
	"gitee.com/igolang/pkg/xtime"
	"gitee.com/igolang/pkg/xutils"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"gorm.io/gen"
	"strings"
	"time"
)

func (s *user) Profile(ctx *gin.Context) (map[string]any, error) {
	userInfo := tools.GetUserInfo(ctx)
	if userInfo.User.SysUser == nil {
		return nil, httpResp.ErrorCode(httpResp.ErrCodeNotFound)
	}

	data, err := s.info(userInfo.User.UserID)
	if err != nil {
		return nil, err
	}
	data["admin"] = userInfo.User.UserID == constants.SuperAdminId
	// 获取岗位
	prows, err := dao.SysPost.Select(dao.SysPost.PostName).LeftJoin(
		dao.SysUserPost, dao.SysUserPost.PostID.EqCol(dao.SysPost.PostID)).Where(dao.SysUserPost.UserID.Eq(userInfo.User.UserID)).Find()
	if err != nil {
		return nil, err
	}
	result := map[string]any{
		"data": data,
	}
	postGroup := make([]string, 0)
	roleGroup := make([]string, 0)
	for _, v := range prows {
		postGroup = append(postGroup, v.PostName)
	}
	if roleRows, ok := data["roles"].([]*model.SysRole); ok {
		for _, v := range roleRows {
			roleGroup = append(roleGroup, v.RoleName)
		}
	}
	result["roleGroup"] = strings.Join(roleGroup, ",")
	result["postGroup"] = strings.Join(postGroup, ",")

	return result, nil
}

func (s *user) SaveProfile(ctx *gin.Context) error {
	var req entities.UserProfileReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		return req.FormatErr(err)
	}
	userInfo := tools.GetUserInfo(ctx)
	// 校验参数
	conds := []gen.Condition{dao.SysUser.UserID.Neq(userInfo.User.UserID), dao.SysUser.NickName.Eq(req.NickName)}
	if count, _ := dao.SysUser.Where(conds...).Count(); count > 0 {
		return errors.Errorf("修改个人信息失败，用户昵称'%s'已存在", req.NickName)
	}
	if req.Email != "" {
		conds[1] = dao.SysUser.Email.Eq(req.Email)
		if count, _ := dao.SysUser.Where(conds...).Count(); count > 0 {
			return errors.Errorf("修改个人信息失败，邮箱'%s'已存在", req.Email)
		}
	}
	if req.PhoneNumber != "" {
		conds[1] = dao.SysUser.Phonenumber.Eq(req.PhoneNumber)
		if count, _ := dao.SysUser.Where(conds...).Count(); count > 0 {
			return errors.Errorf("修改个人信息失败，手机号'%s'已存在", req.PhoneNumber)
		}
	}
	row, err := dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Take()
	if err != nil {
		return err
	}

	row.NickName = req.NickName
	row.Email = req.Email
	row.Phonenumber = req.PhoneNumber
	row.Sex = req.Sex
	row.UpdateTime = xtime.Time(time.Now())
	row.UpdateBy = userInfo.User.UserName
	data := xgorm.ModelToMap(row)
	_, err = dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Updates(data)
	if err == nil {
		s.LoginUserClean(userInfo.User.UserID)
	}
	return err
}

func (s *user) ProfileUpdatePwd(ctx *gin.Context) error {
	var req struct {
		OldPassword string `json:"oldPassword"`
		NewPassword string `json:"newPassword"`
	}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		return err
	}
	if req.OldPassword == "" || req.NewPassword == "" {
		return httpResp.ErrorCode(httpResp.ErrCodeInvalidParams)
	}
	if req.OldPassword == req.NewPassword {
		return httpResp.ErrorCode(httpResp.ErrCodeInvalidParams, "新密码和旧密码不能相同")
	}
	if tools.PasswordCheck(req.NewPassword) != nil {
		return httpResp.ErrorCode(httpResp.ErrCodeInvalidParams, constants.PasswordErr.Error())
	}
	userInfo := tools.GetUserInfo(ctx)
	if userInfo.User.SysUser == nil {
		return httpResp.ErrorCode(httpResp.ErrCodeNotFound)
	}
	row, err := dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Take()
	if err != nil {
		return err
	}
	if !xutils.PasswordVerify(req.OldPassword, row.Password) {
		return httpResp.ErrorCode(httpResp.ErrCodeInvalidParams, "修改密码失败，旧密码错误")
	}
	password, err := xutils.PasswordHash(req.NewPassword)
	if err != nil {
		return err
	}
	row.Password = password
	row.UpdateTime = xtime.Time(time.Now())
	row.UpdateBy = userInfo.User.UserName
	data := xgorm.ModelToMap(row)
	_, err = dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Updates(data)
	return err
}

func (s *user) ProfileAvatar(ctx *gin.Context) (string, error) {
	avatarfile, err := ctx.FormFile("avatarfile")
	if err != nil {
		return "", err
	}
	userInfo := tools.GetUserInfo(ctx)
	row, err := dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Take()
	if err != nil {
		return "", err
	}
	file, err := storage.Upload(avatarfile)
	if err != nil {
		return "", err
	}
	row.Avatar = file.FileName
	row.UpdateTime = xtime.Time(time.Now())
	row.UpdateBy = userInfo.User.UserName
	data := xgorm.ModelToMap(row)
	_, err = dao.SysUser.Where(dao.SysUser.UserID.Eq(userInfo.User.UserID)).Updates(data)
	if err == nil {
		s.LoginUserClean(userInfo.User.UserID)
		return file.FileName, nil
	}
	return "", err

}
